Estoy creando una aplicación y configurando las reglas de Firestore para que solo permitan a los usuarios CRUD acceder a sus datos en una base de datos simple de una sola capa.
Reglas de Firestore
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /todos/{userId} { allow create, read, update, delete: if request.auth != null && request.auth.uid == userId; } } } Si solo uso la declaración if request.auth != null , el usuario puede ver todos los datos en la base de datos.
cuando agrego && request.auth.uid == userId obtengo el error de la consola, "react_devtools_backend.js:4061 Error no detectado en el oyente de instantáneas: FirebaseError: Permisos faltantes o insuficientes". El usuario no puede ver ningún dato, incluido el suyo propio.
He leído los documentos , pero me falta algo: creo que en mi consulta, en mi instantánea o en ambos.
Iniciar base de fuego (firebase.js)
// init Firebase export const app = initializeApp(firebaseConfig); //init services export const db = getFirestore(app); export const auth = getAuth();y luego mi consulta e instantánea (app.js)
import React, { useState, useEffect } from "react"; import Button from "react-bootstrap/Button"; import Form from "react-bootstrap/Form"; import InputGroup from "react-bootstrap/InputGroup"; import "./App.css"; import Todo from "./components/Todo"; import { db } from "./firebase"; import { collection, query, orderBy, onSnapshot, addDoc, serverTimestamp, } from "firebase/firestore"; //collection ref, order by functionality const q = query( collection(db, "todos"), orderBy("timestamp", "desc") ); //firebase functionality function App({ user }) { const [todos, setTodos] = useState([]); const [input, setInput] = useState(""); useEffect(() => { onSnapshot(q, (snapshot) => { setTodos( snapshot.docs.map((doc) => ({ id: doc.id, item: doc.data(), })) ); }); }, [input]); const addTodo = (e) => { e.preventDefault(); addDoc(collection(db, "todos"), { todo: input, timestamp: serverTimestamp(), userId: user.uid, }); setInput(""); };Agradecería cualquier orientación/consejos. He estado trabajando en esto durante un par de días. ¡Gracias!
Con la guía de Frank pude encontrar una solución. ¡Gracias franco!
Estas son mis reglas actualizadas
rules_version = '2'; service cloud.firestore { match /{todos=**} { allow read, update, delete: if request.auth != null && resource.data.userId == request.auth.uid; allow create: if request.auth !=null; } }Mi consulta e instantánea actualizadas
import React, { useState, useEffect } from "react"; import Button from "react-bootstrap/Button"; import Form from "react-bootstrap/Form"; import InputGroup from "react-bootstrap/InputGroup"; import "./App.css"; import Todo from "./components/Todo"; import { collection, query, orderBy, onSnapshot, addDoc, serverTimestamp, where, } from "firebase/firestore"; import { db } from "./firebase"; //firebase functionality function App({ user }) { const [todos, setTodos] = useState([]); const [input, setInput] = useState(""); const [lastChange, setLastChange] = useState(""); //executing the query useEffect(() => { //console.log(user); if (user == null) return; var q = query( collection(db, "todos"), orderBy("timestamp", "desc"), where("userId", "==", user.uid) ); onSnapshot(q, (snapshot) => { setTodos( snapshot.docs.map((doc) => ({ id: doc.id, item: doc.data(), })) ); }); }, [lastChange, user]); //add a new task const addTodo = (e) => { e.preventDefault(); addDoc(collection(db, "todos"), { todo: input, timestamp: serverTimestamp(), userId: user.uid, }); setInput(""); setLastChange(serverTimestamp()); };Tus reglas de seguridad permiten al usuario leer exactamente un documento, en la ruta /todos/$uid . Sin embargo, su código intenta leer toda la colección de todos , lo que las reglas no permiten. Eso explica el error que obtienes.
Tenga en cuenta que las reglas no son filtros , sino que simplemente hacen cumplir que no está tratando de leer (o escribir) más datos de los permitidos. Si desea leer el documento del usuario actual, debe esperar hasta que se cargue el usuario actual (usando un oyente de estado de autenticación ) y luego solo cargue el documento de ese usuario.